package org.xxpay.core.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author frank
 * @date 2020-01-04
 * @email:345690014@qq.com
 */
public class BtUtil {

//    public static final String btSign = "6y5I0jEYTaUEkzJhUArGSdD8Ku1bjw0D";
//    public static final String url = "http://192.168.0.118:8888/";

    public static void main(String[] args)
    {
        try {
        String btSign = "6y5I0jEYTaUEkzJhUArGSdD8Ku1bjw0D";
//        String url = "http://192.168.0.118:8888/firewall?action=DelDropAddress";
        String url = "http://192.168.0.118:8888/data?action=getData";
        String timestamp = (new Date().getTime()+"");
        String md5Sign = getMd5(btSign);
        String temp = timestamp+md5Sign;
        String token = getMd5(temp);

        /*
        * 获取防火墙列表
        * http://192.168.0.118:8888/data?action=getData
        * 参数：tojs=firewall.get_list&table=firewall&limit=10&p=2&search=&order=id desc
        * 响应：
        * {
          "data": [
            {
              "status": -1,
              "ps": "test2",
              "id": 19,
              "addtime": "2020-11-05 11:05:56",
              "port": "11.33.44.55"
            },
            {
              "status": -1,
              "ps": "test",
              "id": 18,
              "addtime": "2020-11-05 11:05:22",
              "port": "12.22.33.44"
            },
            {
              "status": 0,
              "ps": "nexus",
              "id": 16,
              "addtime": "2019-09-20 21:30:20",
              "port": "8081"
            },
            {
              "status": 0,
              "ps": "xxpay-isv",
              "id": 15,
              "addtime": "2019-08-30 09:28:58",
              "port": "8206"
            },
            {
              "status": 0,
              "ps": "xxpay-agent",
              "id": 13,
              "addtime": "2019-08-28 15:56:54",
              "port": "8203"
            },
            {
              "status": 0,
              "ps": "xxpay-manage",
              "id": 12,
              "addtime": "2019-08-28 15:56:26",
              "port": "8202"
            },
            {
              "status": 0,
              "ps": "xxpay-merchant",
              "id": 11,
              "addtime": "2019-08-28 15:56:06",
              "port": "8204"
            },
            {
              "status": 0,
              "ps": "xxpay-pay",
              "id": 10,
              "addtime": "2019-08-28 15:55:47",
              "port": "8201"
            },
            {
              "status": 2,
              "ps": "\u6570\u636e\u5e93",
              "id": 9,
              "addtime": "2019-08-28 15:24:45",
              "port": "3306"
            },
            {
              "status": 2,
              "ps": "",
              "id": 8,
              "addtime": "2019-08-28 15:24:27",
              "port": "888"
            }
          ],
          "where": "",
          "page": "<div><span class='Pcurrent'>1</span><a class='Pnum' onclick='firewall.get_list(2)'>2</a><a class='Pnext' onclick='firewall.get_list(2)'>\u4e0b\u4e00\u9875</a><a class='Pend' onclick='firewall.get_list(2)'>\u5c3e\u9875</a><span class='Pcount'>\u517116\u6761\u6570\u636e</span></div>"
        }
        *
        * 添加防火墙
        * http://192.168.0.118:8888/firewall?action=AddDropAddress
        * 参数： port=1.222.11.22&type=address&ps=test_ip
        * 响应：{"status": true, "msg": "\u6dfb\u52a0\u6210\u529f"}
        *
        *
        * 删除防火墙
        * http://192.168.0.118:8888/firewall?action=DelDropAddress
        * 参数：id=17&port=1.222.11.22
        * 响应：
        *
        *
        *
        *
        * */


        String json = "request_time="+timestamp+"&request_token="+token;

        // tojs=firewall.get_list&table=firewall&limit=10&p=2&search=&order=id desc
        String param = "tojs=firewall.get_list&table=firewall&limit=1000&p=1&search=test&order=id desc";

//        String param = "port=1.222.11.55&type=address&ps=test_ip3";

//        String param = "id=20&port=";

        String responseText = sendPost(url,json + "&" + param);

//        List<JSONObject> ipList = getIpList();
//        String s = addShieldIp("1.1.1.2");
//        String removeShieldIp = removeShieldIp("1.1.1.2");

        System.out.println(responseText);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static String getPostJson(String btSign) {
        try {
            Random random = new Random();
            Long randomNum = Long.valueOf(random.nextInt(1000)+1);
            String timestamp = (new Date().getTime()-randomNum+"");      // 减少随机1秒内参数防止请求失败及签名失败问题
            String md5Sign = getMd5(btSign);
            String temp = timestamp+md5Sign;
            String token = getMd5(temp);
            return "request_time="+timestamp+"&request_token="+token;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取5000条防火墙列表
     * @return
     */
    public static List<JSONObject> getIpList(String btSign, String btUrl) {
        String param = "tojs=firewall.get_list&table=firewall&limit=5000&p=1&search=test&order=id desc";
        String postJson = getPostJson(btSign);
        String responseText = sendPost(btUrl + "/data?action=getData",postJson + "&" + param);
        JSONArray jsonArray = JSONArray.parseArray(JsonUtil.getJSONObjectFromJson(responseText).getString("data"));
        List<JSONObject> objects = new LinkedList<>();
        if (jsonArray == null) return objects;
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject object = (JSONObject) JSON.toJSON(jsonArray.get(i));
            if (isIP(object.getString("port"))) {
                objects.add(object);
            }
        }
        return  objects;
    }

    /**
     * 新增屏蔽IP
     * @param ip
     * @param remark
     * @return
     */
    public static String addShieldIp(String btSign, String btUrl, String ip, String remark) {
        String param = "port="+ip+"&type=address&ps="+remark;
        String postJson = getPostJson(btSign);
        String responseText = sendPost(btUrl + "/firewall?action=AddDropAddress",postJson + "&" + param);
        return responseText;
    }

    /**
     * 解除屏蔽IP
     * @param id
     * @param ip
     * @return
     */
    public static String removeShieldIp(String btSign, String btUrl, String id, String ip) {
        String param = "id="+id+"&port="+ip;
        String postJson = getPostJson(btSign);
        String responseText = sendPost(btUrl + "/firewall?action=DelDropAddress",postJson + "&" + param);
        return responseText;
    }

    /**
     * 宝塔配置检测
     * @param btSign
     * @param btUrl
     * @return
     */
    public static Boolean testBtConfig(String btSign, String btUrl) {
        String postJson = getPostJson(btSign);
        String responseText = sendPost(btUrl + "/system?action=GetSystemTotal", postJson);
        if (StringUtils.isEmpty(responseText)) return false;
        String status = JsonUtil.getJSONObjectFromJson(responseText).getString("status");
        if ("false".equals(status)) return false;
        return true;
    }

    /**
     * 判断是否为ip
     * @param addr
     * @return
     */
    public static Boolean isIP(String addr) {
        if(addr.length() < 7 || addr.length() > 15 || "".equals(addr)) {
            return false;
        }
        /**
         * 判断IP格式和范围
         */
        String rexp = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
        Pattern pat = Pattern.compile(rexp);
        Matcher mat = pat.matcher(addr);
        boolean ipAddress = mat.find();
        return ipAddress;
    }

    public static String getMd5(String str) throws Exception
    {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes());
            // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
            throw new Exception("MD5加密出现错误，"+e.toString());
        }
    }

    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuffer result = new StringBuffer();
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "text/xml,text/javascript,text/html,application/json");
            conn.setRequestProperty("connection", "Keep-Alive");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result.toString();
    }

}
